package main

import (
	"fmt"
)

//copy 专门用来进行深拷贝的
func main() {
	a1 := []int{1, 3, 5} //声明int类型切片并初始化
	a2 := a1
	fmt.Printf("a1存值内存地址: num1:%p\n", a1)
	fmt.Printf("a2存值内存地址: num2:%p\n", a2)
	var a3 = make([]int, 3, 5)
	fmt.Println(a3)
	fmt.Printf("a3存值的内存地址: a3:%p\n", a3)
	copy(a3, a1) //将a1的值copy到a3中copy(目标，源，T类型)
	fmt.Println(a1, a2, a3)
	fmt.Printf("a3存值的内存地址: a3:%p\n", a3)
	fmt.Printf("a3=%v len(a3)=%d cap(a3)=%d\n", a3, len(a3), cap(a3))
	//将a1中的索引为1的值给删除掉
	a1 = append(a1[:1], a1[2:]...) //...代表拆开数组，切片不存值，底层数组存值
	//append干掉元素“3”后，其后的元素前移，所以元素“3”的位置由“5”代替，但是元素“5”的位置没有元素来代替它，保留原值(因为初始化时的内存地址与现在的内存地址相同，所以它的的长度和容量都要保持为初始化时的3 3)。所以append操作完后内存0xc00000a240存的值就变为了“1 5 5”。
	fmt.Printf("a1删除部分元素后存值的内存地址: num1:%p\n", a1)
	fmt.Printf("a1删除部分元素后a2存值内存地址: num2:%p\n", a2)
	fmt.Printf("a1=%v len(a1)=%d cap(a1)=%d\n", a1, len(a1), cap(a1)) //[1 5] 2 3
	fmt.Printf("a2=%v len(a2)=%d cap(a2)=%d\n", a2, len(a2), cap(a2)) //[1 5 5] 3 3
	fmt.Println(a1, a2, a3)                                           //虽然append后的a1与a2指向的内存地址仍然相同，但是长度不通，导致打印的结果也就不同了  a3的值之所以还是135是因为a3的底层数组地址与a1的不同

	a4 := [...]int{1, 5, 6, 8} //定义数组
	s3 := a4[:]                //定义一个切片
	fmt.Printf("a4存值内存地址: num4:%p\n", &a4)
	fmt.Printf("s3存值内存地址: num4:%p\n", s3)
	fmt.Println(s3, len(s3), cap(s3))
	//删除元素之后的切片会覆盖掉原来的底层数组元素
	//也就是说每当删除一个值时，底层数组会发生相应的改变。
	s3 = append(a4[:1], a4[3:]...) //在此处进行数组元素删除操作时,会对底层的数组的值进行修改，因此在最后打印底层数组a4时，值为1868
	fmt.Println(a4, len(a4), cap(a4))
	fmt.Println(s3, len(s3), cap(s3))
	fmt.Printf("append后s3存值内存地址: num5:%p\n", s3)
	fmt.Printf("append后a4存值内存地址: num5:%p\n", a4)
	fmt.Println(a4)

	a5 := [3]int{1, 2, 3}
	a6 := a5[:]
	fmt.Printf("a5的内存地址%p\n", a5)
	fmt.Printf("a6的内存地址%p\n", a6)
	a6 = append(a5[:1], a5[2:]...)
	fmt.Printf("append后a5的内存地址%p\n", a5)
	fmt.Printf("append后a6的内存地址%p\n", a6)
	a6[0] = 7
	fmt.Printf("append后a5的内存地址%p\n", a5)
	fmt.Printf("append后a6的内存地址%p\n", a6)
	fmt.Printf("a1=%v len(a1)=%d cap(a1)=%d\n", a5, len(a5), cap(a5)) //[1 5] 2 3
	fmt.Printf("a2=%v len(a2)=%d cap(a2)=%d\n", a6, len(a6), cap(a6))

}

//切片的性质
//1.切片的容量 是指从切片的第一个元素到底层数组的最后一个元素的个数数量，只能向后拓展
//2.切片再切片 切片的容量仍然是指到底层数组的最后一个元素的个数数量
//3.切片是一个引用类型，切片对应一个底层数组
//4.切片只是一个框，不保存具体的值，真正存放的元素的是底层数组
//5.append追加元素时，原来的底层数组放不下的时候，Go底层就会换一个新的底层数组，为了防止原来的切片丢失，需要用原来的切片来进行接收
//6.底层数组都是占用一块连续的内存空间
